﻿Imports System.Collections.Specialized
Imports System.Text

Public Class clsDotMatrix


#Region "Public structure"

  


#End Region


#Region "Private class level variables"

    Private Shared _thisInstance As clsDotMatrix
    '  Private c_visibleList As List(Of clsLibraryEntry)
    Private c_selectedItem As clsLibraryEntry
    Private c_MaxLevels As Byte = 3
    Private c_DisplayLines() As String
    Private c_NumLines As Byte
    Private c_Library As clsLibraryHeader


#End Region


#Region "Public Properties"


    Public ReadOnly Property Library() As clsLibraryHeader
        Get
            Return c_Library
        End Get
    End Property

    Public Property LibraryName() As String
        Get
            Return c_Library.LibraryName
        End Get
        Set(ByVal value As String)
            c_Library.LibraryName = value
        End Set
    End Property

    Public Property MaxLevels() As Byte
        Get
            Return c_MaxLevels
        End Get
        Set(ByVal value As Byte)
            c_MaxLevels = value
        End Set
    End Property
    Public Property NumLines() As Byte
        Get
            Return c_NumLines
        End Get
        Set(ByVal value As Byte)
            c_NumLines = value
        End Set
    End Property

    Public Property DisplayLines() As String()
        Get

            Return c_DisplayLines
        End Get
        Set(ByVal value As String())

            c_DisplayLines = value
        End Set
    End Property

#End Region

#Region "Public events"

    Public Event DataChanged()

    Public Event ViewChanged()


#End Region


#Region "Public methods"

    Public Shared Function GetSingleton() As clsDotMatrix

        ' initialize object if it hasn't already been done
        If _thisInstance Is Nothing Then
            _thisInstance = New clsDotMatrix
        End If

        ' return the initialized instance
        Return _thisInstance

    End Function

    Public Sub LoadLibrary(ByVal path As String)
        'Create as serializer and get the file to deserialize
        Dim extraTypes(0) As Type

        extraTypes(0) = GetType(clsInstrument)


        Dim ser As New System.Xml.Serialization.XmlSerializer(GetType(clsLibraryHeader), extraTypes)
        Dim file As New System.IO.FileStream(path, IO.FileMode.Open)
        Dim reader As New System.Xml.XmlTextReader(file)

        'Deserialize the file and populate the treeview

        c_Library = CType(ser.Deserialize(reader), clsLibraryHeader)

        'Tidy up
        reader.Close()
        file.Close()
        file = Nothing

        Me.Refresh()

        ProcessUpdate()

    End Sub

    Public Sub NewLibrary()

        Dim newRootEntry As New clsLibraryEntry


        c_Library = New clsLibraryHeader
        c_Library.LibraryName = "<<Library>>"
        c_Library.Entries = New List(Of clsLibraryEntry)


        With newRootEntry
            .Name = "<< library entries >>"
            .Level = 1
            .UID = Guid.NewGuid()
            .Sort = 1
        End With

        c_Library.Entries.Add(newRootEntry)

        AddDefaultChildren(newRootEntry, 1)


        ProcessUpdate()

    End Sub

    Public Sub AddItem(ByVal parentUID As Guid, ByVal Level As Int32, ByVal SortOrder As Int32, Optional ByVal name As String = "", Optional ByVal detail As Object = Nothing)

        Dim newEntry As New clsLibraryEntry
        With newEntry
            .ParentUID = parentUID
            .Level = Level
            If name = "" Then
                .Name = "<< new item L" + Level.ToString + " >>"
            Else
                .Name = name
            End If
            .UID = Guid.NewGuid()
            .Sort = SortOrder
            If Not detail Is Nothing Then
                .Detail = detail
            End If
        End With
        c_Library.Entries.Add(newEntry)

        For Each objItem As clsLibraryEntry In SelectChildren(Level - 1, parentUID)
            If objItem.Sort >= SortOrder Then
                objItem.Sort += 1
            End If
        Next

        AddDefaultChildren(newEntry, Level)

        ProcessUpdate()

    End Sub


    Private Sub AddDefaultChildren(ByVal rootEntry As clsLibraryEntry, ByVal fromLevel As Byte)

        Dim childEntry As clsLibraryEntry()

        ReDim childEntry(c_MaxLevels - 1)
        For i As Byte = fromLevel - 1 To c_MaxLevels - 2
            childEntry(i) = New clsLibraryEntry
            childEntry(i).Level = i + 2
            childEntry(i).Name = "<< new item L" + (i + 2).ToString + " >>"
            childEntry(i).UID = Guid.NewGuid()
            childEntry(i).Sort = 1
            If i = fromLevel - 1 Then
                childEntry(i).ParentUID = rootEntry.UID
            Else
                childEntry(i).ParentUID = childEntry(i - 1).UID
            End If
            c_Library.Entries.Add(childEntry(i))
        Next

    End Sub

    Public Sub RenameItem(ByVal UID As Guid, ByVal NewName As String)

        Dim objEntry = c_Library.Entries.Where(Function(entry) entry.UID = UID)(0)

        If Not objEntry Is Nothing Then
            objEntry.Name = NewName
        End If

        ProcessUpdate()

    End Sub

    Public Sub UpdateItemDetail(ByVal UID As Guid, ByVal Name As String, ByVal detail As Object)

        Dim objEntry = c_Library.Entries.Where(Function(entry) entry.UID = UID)(0)

        If Not objEntry Is Nothing Then
            objEntry.Name = Name
            objEntry.Detail = detail
        End If

        ProcessUpdate()

    End Sub

    Public Sub SaveLibrary(ByVal path As String)

        Dim extraTypes(0) As Type

        extraTypes(0) = GetType(clsInstrument)


        Dim ser As New System.Xml.Serialization.XmlSerializer(GetType(clsLibraryHeader), extraTypes)
        Dim file As New System.IO.FileStream(path, IO.FileMode.Create)
        Dim writer As New System.Xml.XmlTextWriter(file, Nothing)

        ser.Serialize(writer, c_Library)

        'Tidy up
        writer.Close()
        file.Close()
        file = Nothing

        ProcessUpdate()

    End Sub

    Public Sub Refresh()
        c_Library.CollapseAll()

        c_selectedItem = c_Library.Entries(0)
        BuildDisplay()
    End Sub

   

    Public Sub ScrollDown()


    End Sub

    Public Sub ScrollUp()


    End Sub

    Public Sub SelectItem()

        Dim objParent As clsLibraryEntry

        'selected item is known

        'collapse all (expanded, NOT breadcrumbs)

        c_Library.CollapseAll()

        'expand this item 

        c_selectedItem.Expanded = True



        'change parent from Expanded to IsBreadcrumb
        objParent = SelectParent(c_selectedItem.Level, c_selectedItem.ParentUID)
        If Not objParent Is Nothing Then
            If objParent.Expanded Then
                objParent.IsBreadcrumb = True
            End If
        End If
 


    End Sub

    Public Sub DeselectItem()
        Dim objParent As clsLibraryEntry

        'if expanded set as not expanded ; 
        If c_selectedItem.Expanded Then
            c_selectedItem.Expanded = False
        End If

        'if Parent IsBreadcrumb set as Expanded

        objParent = SelectParent(c_selectedItem.Level, c_selectedItem.ParentUID)
        If Not objParent Is Nothing Then
            If objParent.IsBreadcrumb Then
                objParent.Expanded = True
            End If
        End If

    End Sub



    Public Function TopLevelEntries() As List(Of clsLibraryEntry)


        Dim lstEntries = c_Library.Entries.Where(Function(entry) entry.Level = 1).ToList()


        Return lstEntries


    End Function

    Public Function SelectChildren(ByVal Level As Byte, ByVal parentUID As Guid) As List(Of clsLibraryEntry)


        Dim lstEntries = c_Library.Entries.Where(Function(entry) entry.Level = (Level + 1) And entry.ParentUID.ToString = parentUID.ToString).ToList()


        Return lstEntries


    End Function



    Public Function SelectParent(ByVal Level As Byte, ByVal ParentUID As Guid) As clsLibraryEntry

        Dim objParentEntry As clsLibraryEntry


        If c_selectedItem.ParentUID <> Guid.Empty Then
            objParentEntry = c_Library.Entries.Where(Function(entry) entry.Level = (Level - 1) And entry.UID.ToString = ParentUID.ToString).ToList().Item(0)
        End If

        Return objParentEntry


    End Function

#End Region


#Region "Private methods"
    Private Sub ProcessUpdate()



        RaiseEvent DataChanged()

        'data has changed - always redisplay from scratch



    End Sub

    Private Sub BuildDisplay()

        Dim idx As Byte = 0

        'build display lines


        ReDim c_DisplayLines(c_NumLines - 1)


        For Each objEntry As clsLibraryEntry In c_Library.Entries
            idx += 1
            If idx > c_NumLines Then
                Exit For
            End If
            If objEntry.Level = 1 Then
                BuildLine(objEntry, idx)
            End If
            If objEntry.Expanded Then
                AddChildToDisplay(objEntry, idx)
                If idx > c_NumLines Then
                    Exit For
                End If
            End If
        Next

        RaiseEvent ViewChanged()


    End Sub

    Private Sub AddChildToDisplay(ByVal objEntry As clsLibraryEntry, ByRef idx As Byte)


        For Each childEntry As clsLibraryEntry In SelectChildren(objEntry.Level, objEntry.UID)
            idx += 1
            If idx > c_NumLines Then
                Exit For
            End If
            BuildLine(childEntry, idx)

            If objEntry.Expanded Then
                AddChildToDisplay(childEntry, idx)
                If idx > c_NumLines Then
                    Exit For
                End If
            End If
        Next


    End Sub


    Private Sub BuildLine(ByVal objentry As clsLibraryEntry, ByVal idx As Byte)

        Dim sbLine As New StringBuilder

        If SelectChildren(objentry.Level, objentry.UID).Count > 0 Then
            sbLine.Append("+")
        Else
            sbLine.Append(" ")
        End If

        For idxLevel As Byte = 0 To objentry.Level - 1
            sbLine.Append("..")
        Next

        sbLine.Append(objentry.Name)

        If c_selectedItem.UID = objentry.UID Then
            sbLine.Append(" <<")
        End If


    End Sub
#End Region


End Class
